import logging
import logging.config
import copy
import threading
import quantities as quantities
import struct
from pyFAMOUSO.subscriber import subscriber

class Channel (subscriber.SubscriberEventChannel):
    
    def __init__(self, subject, logger=[]):    
        self.subject=subject    
        if not logger==[]:
            self.logger=logger
        else:
            logging.config.fileConfig("logging.conf")
            self.logger = logging.getLogger("AFN")
            self.logger.setLevel(logging.DEBUG)
                 
    def __str__(self):
        print "     Name               \"" + str(self.parameter.name) + "\" "
        print "     Subject           ", self.parameter.subject
    
    def connect(self):
        self.LogSubscriber = subscriber.SubscriberEventChannel(self.subject)
        self.LogSubscriber.subscribe(self.subject, self.logCallback)
        output =  "Subscription to \"" + self.subject  + "\""
        self.logger.info(output)   
        
    def set_basic_callback(self, callMethod):
        self.callMethod = callMethod     

    def logCallback(self, myEvent):
        self.callMethod(self.subject, myEvent)

class MeasurementChannel(Channel):

    def __init__(self, parameter, logger=[]):
        Channel.__init__(self, parameter.subject, logger)
        self.parameter=copy.copy(parameter)
        self.missing_message_counter=0
        self.eventMask = ""
        self.prepare_Event_Mask()
        self.lock = threading.Lock()
        self.MessageReceived = False       
        self.timer = threading.Timer(1, self.timeout)
        self.timeout()
        self.filter_callback=[]

    def add_filter_callback(self,callback):
        self.filter_callback.append(callback)

    def timeout(self):
        self.lock.acquire()
        if self.MessageReceived==True:
            self.missing_message_counter=0
        else:
            self.missing_message_counter+=1
        self.MessageReceived = False
        period=self.parameter.period
        period.units=quantities.second
        self.timer = threading.Timer(float(period), self.timeout)
        self.timer.start()
        self.lock.release()
        
    def logCallback(self, myEvent):
        self.lock.acquire()
        self.MessageReceived = True
        self.lock.release()
        self.callMethod(self.subject, myEvent)
        
    def prepare_Event_Mask(self):
        # wo gehoert das eigentlich richtig hin?
        data_types = {'int16': ['h','short'],
                      'int':['i', 'integer'],
                      'float':['f', 'float'],
                      'u_int8':['B', 'unsigned byte'], 
                      'int8_t':['b', 'signed byte']}
        format = ""
        output = "Event format of %s:" % self.parameter.subject
        for elements in self.parameter.event_format:
            try:
                if output<>[]:
                    output=output + '\n'
                symbol = data_types[elements['DataType']]
                output = output + '%25s %s \t %s' % (' ', elements['Name'], symbol[1])
            except:
                output =  "Unknown data type in datasheet of \"" + self.subject  + "\""
                self.logger.error(output)
            for i in range(0,elements['Size']):
                format=format + symbol[0]
        self.eventMask=format
        self.logger.info(output)
        
    def get_abstract_event(self,event):
        event_elements=struct.unpack(self.eventMask,event.content)
        index=0
        abstract_event={}
        for elements in self.parameter.event_format:
            values=event_elements[index:index+elements['Size']]
            if elements.has_key('Dimension'):
                abstract_event[elements['Name']]=elements['Dimension']*values
            else:
                abstract_event[elements['Name']]=values
            index=index+elements['Size']
        abstract_event['Subject']=self.subject
        return abstract_event
            
class DataSheetChannel(Channel):
    """
     # PyUML: Do not remove this line! # XMI_ID:_vWa7KJ4hEd-wxNaAlEK91A
    """
    def __init__(self, logger=[]):
        Channel.__init__(self,"Datashee", logger)
        self.suitable = False
    
    def logCallback(self, myEvent):
        self.callMethod(myEvent)
